package com.ssh.demo.netty;

import com.ssh.demo.config.NettyConfig;
import com.ssh.demo.core.NettyServer;
import com.ssh.demo.helper.ByteArrHelper;
import com.ssh.demo.netty.coder.TcpNettyDecoder;
import com.ssh.demo.netty.coder.TcpNettyEncoder;
import com.ssh.demo.netty.handler.TcpSessionHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * @ClassName TcpNettyServer
 * @Description TODO
 * @Author ssh
 * @Date 2021/4/12 10:43
 */
@Slf4j
@Component("tcp-netty")
@AllArgsConstructor
public class TcpNettyServer implements NettyServer {

    private static Channel tcpChannel;
    private static EventLoopGroup masterGroup;
    private static EventLoopGroup slaveGroup;

    private NettyConfig nettyConfig;
    private ByteArrHelper byteArrHelper;

    @Override
    public boolean start() {
        if(tcpChannel != null){
            return tcpChannel.isActive();
        }

        masterGroup = new NioEventLoopGroup(nettyConfig.getMasterSize());//主线程
        slaveGroup = new NioEventLoopGroup(nettyConfig.getSlaveSize());//工作线程
        ServerBootstrap serverBootstrap = new ServerBootstrap();//引导对象

        serverBootstrap
                .group(masterGroup, slaveGroup)//配置工作线程组
                .channel(NioServerSocketChannel.class)//配置为NIO的socket通道
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {//绑定通道参数
                        socketChannel.pipeline().addLast("encode",new TcpNettyEncoder());//编码器
                        socketChannel.pipeline().addLast("decode",new TcpNettyDecoder());//解码器
                        socketChannel.pipeline().addLast("handler",new TcpSessionHandler(byteArrHelper));//业务处理
                    }
                })
                .childOption(ChannelOption.TCP_NODELAY, nettyConfig.getTcpNoDelay())//允许小包发送
                .childOption(ChannelOption.SO_KEEPALIVE, nettyConfig.getKeepAlive());//开启TCP心跳
        //使用了Future来启动线程，并绑定了端口
        ChannelFuture channelFuture = serverBootstrap.bind(nettyConfig.getTcpPort());
        //以异步的方式关闭端口
        tcpChannel = channelFuture.channel();
        return true;
    }

    @Override
    public boolean stop() {
        tcpChannel.close();
        if (masterGroup != null) {
            masterGroup.shutdownGracefully();
        }
        if (slaveGroup != null) {
            slaveGroup.shutdownGracefully();
        }
        return true;
    }
}
